package com.ly.mp.busicen.rule.extention.auto;

import java.beans.Introspector;
import java.lang.annotation.Annotation;
import java.util.Set;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ClassUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;

import com.ly.mp.busicen.rule.extention.annotation.Xrule;
import com.ly.mp.busicen.rule.flow.IFireFlow;

public class ClassPathXruleScanner extends ClassPathBeanDefinitionScanner {

	protected Class<? extends Annotation> type;

	public ClassPathXruleScanner(BeanDefinitionRegistry registry, Class<? extends Annotation> type) {
		super(registry, false);
		this.type = type;
	}

	@Override
	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Set<BeanDefinitionHolder> beanDefinitionHolders = super.doScan(basePackages);
		processDecorate(beanDefinitionHolders, getResourceLoader(), getEnvironment());
		return beanDefinitionHolders;
	}

	public static void processDecorate(Set<BeanDefinitionHolder> holders, ResourceLoader resourceLoader,
			Environment environment) {
		for (BeanDefinitionHolder beanDefinitionHolder : holders) {
			decorate(beanDefinitionHolder, resourceLoader, environment);
		}
	}

	
	public static void decorate(BeanDefinitionHolder holder, ResourceLoader resourceLoader, Environment environment) {
		ScannedGenericBeanDefinition beanDefinition = (ScannedGenericBeanDefinition) holder.getBeanDefinition();
		AnnotationMetadata visitor = (AnnotationMetadata) beanDefinition.getMetadata();
		MultiValueMap<String, Object> fireFlowAnnotationMap = visitor
				.getAllAnnotationAttributes(Xrule.class.getName());
		
		String fireFlowName = "fireFlow";
		
		if (fireFlowAnnotationMap!=null) {
			@SuppressWarnings("unchecked")
			Class<? extends IFireFlow> proxyType = (Class<? extends IFireFlow>) fireFlowAnnotationMap
					.getFirst("fireFlowEngine");
			fireFlowName = fireFlowAnnotationMap.getFirst("fireFlowEngineName").toString();
			if (StringUtils.isEmpty(fireFlowName)) {
				String shortName = ClassUtils.getShortName(proxyType);
				fireFlowName = Introspector.decapitalize(shortName);
			}
		}
		
		
		beanDefinition.getPropertyValues().add("fireFlow", new RuntimeBeanReference(fireFlowName));
		beanDefinition.getPropertyValues().add("innerClassName", beanDefinition.getBeanClassName());
		beanDefinition.setBeanClass(XruleFactoryBean.class);
	}

	@Override
	protected void registerDefaultFilters() {
		// addIncludeFilter(new AnnotationTypeFilter(type));
		addIncludeFilter((metadataReader, metadataReaderFactory) -> true);
	}

	@Override
	protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
		return true;// beanDefinition.getMetadata().hasMetaAnnotation(type.getName());
	}

}
